home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / inet / rcmd.c < prev    next >
C/C++ Source or Header  |  1994-06-03  |  9KB  |  352 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)rcmd.c    5.24 (Berkeley) 2/24/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/socket.h>
  40. #include <sys/stat.h>
  41. #include <netinet/in.h>
  42. #include <arpa/inet.h>
  43. #include <signal.h>
  44. #include <fcntl.h>
  45. #include <netdb.h>
  46. #include <pwd.h>
  47. #include <errno.h>
  48. #include <stdio.h>
  49. #include <ctype.h>
  50. #include <unistd.h>
  51. #include <string.h>
  52.  
  53. rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
  54.     char **ahost;
  55.     u_short rport;
  56.     const char *locuser, *remuser, *cmd;
  57.     int *fd2p;
  58. {
  59.     int s, timo = 1, pid;
  60.     long oldmask;
  61.     struct sockaddr_in sin, sin2, from;
  62.     char c;
  63.     int lport = IPPORT_RESERVED - 1;
  64.     struct hostent *hp;
  65.     fd_set reads;
  66.  
  67.     pid = getpid();
  68.     hp = gethostbyname(*ahost);
  69.     if (hp == 0) {
  70.         herror(*ahost);
  71.         return (-1);
  72.     }
  73.     *ahost = hp->h_name;
  74.     oldmask = sigblock(sigmask(SIGURG));
  75.     for (;;) {
  76.         s = rresvport(&lport);
  77.         if (s < 0) {
  78.             if (errno == EAGAIN)
  79.                 fprintf(stderr, "socket: All ports in use\n");
  80.             else
  81.                 perror("rcmd: socket");
  82.             sigsetmask(oldmask);
  83.             return (-1);
  84.         }
  85.         fcntl(s, F_SETOWN, pid);
  86.         sin.sin_family = hp->h_addrtype;
  87.         bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
  88.         sin.sin_port = rport;
  89.         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  90.             break;
  91.         (void) close(s);
  92.         if (errno == EADDRINUSE) {
  93.             lport--;
  94.             continue;
  95.         }
  96.         if (errno == ECONNREFUSED && timo <= 16) {
  97.             sleep(timo);
  98.             timo *= 2;
  99.             continue;
  100.         }
  101.         if (hp->h_addr_list[1] != NULL) {
  102.             int oerrno = errno;
  103.  
  104.             fprintf(stderr,
  105.                 "connect to address %s: ", inet_ntoa(sin.sin_addr));
  106.             errno = oerrno;
  107.             perror(0);
  108.             hp->h_addr_list++;
  109.             bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
  110.                 hp->h_length);
  111.             fprintf(stderr, "Trying %s...\n",
  112.                 inet_ntoa(sin.sin_addr));
  113.             continue;
  114.         }
  115.         perror(hp->h_name);
  116.         sigsetmask(oldmask);
  117.         return (-1);
  118.     }
  119.     lport--;
  120.     if (fd2p == 0) {
  121.         write(s, "", 1);
  122.         lport = 0;
  123.     } else {
  124.         char num[8];
  125.         int s2 = rresvport(&lport), s3;
  126.         int len = sizeof (from);
  127.  
  128.         if (s2 < 0)
  129.             goto bad;
  130.         listen(s2, 1);
  131.         (void) sprintf(num, "%d", lport);
  132.         if (write(s, num, strlen(num)+1) != strlen(num)+1) {
  133.             perror("write: setting up stderr");
  134.             (void) close(s2);
  135.             goto bad;
  136.         }
  137.         FD_ZERO(&reads);
  138.         FD_SET(s, &reads);
  139.         FD_SET(s2, &reads);
  140.         errno = 0;
  141.         if (select(1 + (s > s2 ? s : s2), &reads, 0, 0, 0) < 1 ||
  142.             !FD_ISSET(s2, &reads)) {
  143.             if (errno != 0)
  144.                 perror("select: setting up stderr");
  145.             else
  146.                 fprintf(stderr,
  147.                 "select: protocol failure in circuit setup.\n");
  148.             (void) close(s2);
  149.             goto bad;
  150.         }
  151.         s3 = accept(s2, (struct sockaddr *)&from, &len);
  152.         (void) close(s2);
  153.         if (s3 < 0) {
  154.             perror("accept");
  155.             lport = 0;
  156.             goto bad;
  157.         }
  158.         *fd2p = s3;
  159.         from.sin_port = ntohs((u_short)from.sin_port);
  160.         if (from.sin_family != AF_INET ||
  161.             from.sin_port >= IPPORT_RESERVED ||
  162.             from.sin_port < IPPORT_RESERVED / 2) {
  163.             fprintf(stderr,
  164.                 "socket: protocol failure in circuit setup.\n");
  165.             goto bad2;
  166.         }
  167.     }
  168.     (void) write(s, locuser, strlen(locuser)+1);
  169.     (void) write(s, remuser, strlen(remuser)+1);
  170.     (void) write(s, cmd, strlen(cmd)+1);
  171.     if (read(s, &c, 1) != 1) {
  172.         perror(*ahost);
  173.         goto bad2;
  174.     }
  175.     if (c != 0) {
  176.         while (read(s, &c, 1) == 1) {
  177.             (void) write(2, &c, 1);
  178.             if (c == '\n')
  179.                 break;
  180.         }
  181.         goto bad2;
  182.     }
  183.     sigsetmask(oldmask);
  184.     return (s);
  185. bad2:
  186.     if (lport)
  187.         (void) close(*fd2p);
  188. bad:
  189.     (void) close(s);
  190.     sigsetmask(oldmask);
  191.     return (-1);
  192. }
  193.  
  194. rresvport(alport)
  195.     int *alport;
  196. {
  197.     struct sockaddr_in sin;
  198.     int s;
  199.  
  200.     sin.sin_family = AF_INET;
  201.     sin.sin_addr.s_addr = INADDR_ANY;
  202.     s = socket(AF_INET, SOCK_STREAM, 0);
  203.     if (s < 0)
  204.         return (-1);
  205.     for (;;) {
  206.         sin.sin_port = htons((u_short)*alport);
  207.         if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  208.             return (s);
  209.         if (errno != EADDRINUSE) {
  210.             (void) close(s);
  211.             return (-1);
  212.         }
  213.         (*alport)--;
  214.         if (*alport == IPPORT_RESERVED/2) {
  215.             (void) close(s);
  216.             errno = EAGAIN;        /* close */
  217.             return (-1);
  218.         }
  219.     }
  220. }
  221.  
  222. int    _check_rhosts_file = 1;
  223.  
  224. ruserok(rhost, superuser, ruser, luser)
  225.     const char *rhost, *ruser, *luser;
  226.     int superuser;
  227. {
  228.     FILE *hostf;
  229.     char fhost[MAXHOSTNAMELEN];
  230.     int first = 1;
  231.     register char *sp, *p;
  232.     int baselen = -1;
  233.  
  234.     sp = (char *)rhost;
  235.     p = fhost;
  236.     while (*sp) {
  237.         if (*sp == '.') {
  238.             if (baselen == -1)
  239.                 baselen = sp - rhost;
  240.             *p++ = *sp++;
  241.         } else {
  242.             *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
  243.         }
  244.     }
  245.     *p = '\0';
  246.     hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r");
  247. again:
  248.     if (hostf) {
  249.         if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
  250.             (void) fclose(hostf);
  251.             return(0);
  252.         }
  253.         (void) fclose(hostf);
  254.     }
  255.     if (first == 1 && (_check_rhosts_file || superuser)) {
  256.         struct stat sbuf;
  257.         struct passwd *pwd;
  258.         char pbuf[MAXPATHLEN];
  259.  
  260.         first = 0;
  261.         if ((pwd = getpwnam(luser)) == NULL)
  262.             return(-1);
  263.         (void)strcpy(pbuf, pwd->pw_dir);
  264.         (void)strcat(pbuf, "/.rhosts");
  265.         if ((hostf = fopen(pbuf, "r")) == NULL)
  266.             return(-1);
  267.         /*
  268.          * if owned by someone other than user or root or if
  269.          * writeable by anyone but the owner, quit
  270.          */
  271.         if (fstat(fileno(hostf), &sbuf) ||
  272.             sbuf.st_uid && sbuf.st_uid != pwd->pw_uid ||
  273.             sbuf.st_mode&022) {
  274.             fclose(hostf);
  275.             return(-1);
  276.         }
  277.         goto again;
  278.     }
  279.     return (-1);
  280. }
  281.  
  282. /* don't make static, used by lpd(8) */
  283. _validuser(hostf, rhost, luser, ruser, baselen)
  284.     char *rhost, *luser, *ruser;
  285.     FILE *hostf;
  286.     int baselen;
  287. {
  288.     register char *p;
  289.     char *user, ahost[MAXHOSTNAMELEN];
  290.     static int _checkhost();
  291.  
  292.     while (fgets(ahost, sizeof (ahost), hostf)) {
  293.         p = ahost;
  294.         while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
  295.             *p = isupper(*p) ? tolower(*p) : *p;
  296.             p++;
  297.         }
  298.         if (*p == ' ' || *p == '\t') {
  299.             *p++ = '\0';
  300.             while (*p == ' ' || *p == '\t')
  301.                 p++;
  302.             user = p;
  303.             while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
  304.                 p++;
  305.         } else
  306.             user = p;
  307.         *p = '\0';
  308.         if (_checkhost(rhost, ahost, baselen) &&
  309.             !strcmp(ruser, *user ? user : luser)) {
  310.             return (0);
  311.         }
  312.     }
  313.     return (-1);
  314. }
  315.  
  316. static
  317. _checkhost(rhost, lhost, len)
  318.     char *rhost, *lhost;
  319.     int len;
  320. {
  321.     static char ldomain[MAXHOSTNAMELEN + 1];
  322.     static char *domainp = NULL;
  323.     static int nodomain = 0;
  324.     register char *cp;
  325.  
  326.     if (len == -1)
  327.         return(!strcmp(rhost, lhost));
  328.     if (strncmp(rhost, lhost, len))
  329.         return(0);
  330.     if (!strcmp(rhost, lhost))
  331.         return(1);
  332.     if (*(lhost + len) != '\0')
  333.         return(0);
  334.     if (nodomain)
  335.         return(0);
  336.     if (!domainp) {
  337.         if (gethostname(ldomain, sizeof(ldomain)) == -1) {
  338.             nodomain = 1;
  339.             return(0);
  340.         }
  341.         ldomain[MAXHOSTNAMELEN] = NULL;
  342.         if ((domainp = index(ldomain, '.')) == (char *)NULL) {
  343.             nodomain = 1;
  344.             return(0);
  345.         }
  346.         for (cp = ++domainp; *cp; ++cp)
  347.             if (isupper(*cp))
  348.                 *cp = tolower(*cp);
  349.     }
  350.     return(!strcmp(domainp, rhost + len +1));
  351. }
  352.